package translate;

import Base.ResourceTest;
import EntityBuilder.RenterBuilder;
import com.huawei.translate.api.TranslateApi;
import com.huawei.translate.model.Renter;
import com.huawei.translate.provider.MSTranslateProvider;
import com.huawei.translate.service.TranslateRecordService;
import com.huawei.translate.vo.AccessTokenGenerateRequest;
import com.huawei.translate.vo.AccessTokenResponse;
import com.huawei.translate.vo.translate.DetectRequest;
import com.huawei.translate.vo.translate.DetectResponse;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.UUID;

import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.*;

@RunWith(SpringRunner.class)
public class When_request_detect_language extends ResourceTest {

    @Autowired
    @Mock
    private MSTranslateProvider msTranslateProvider;

    @Autowired
    @Mock
    private TranslateRecordService translateRecordService;

    @Autowired
    @InjectMocks
    private TranslateApi translateApi;

    private Renter renter;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void should_record_detect_log_when_detect_language() {
        renter = new RenterBuilder(renterRepository).WithAppSecret(UUID.randomUUID().toString()).Build();
        ResponseEntity<AccessTokenResponse> accessTokenResponse = generateAccessToken();

        when(msTranslateProvider.detect(isA(String.class))).thenReturn("en");
        doNothing().when(translateRecordService).recordDetect(isA(DetectRequest.class),anyString());
        DetectRequest detectRequest = new DetectRequest();
        detectRequest.setContent("hello");
        detectRequest.setAccessToken(accessTokenResponse.getBody().getAccessToken());
        sendDetectLanguageRequest(detectRequest);

        verify(translateRecordService,times(1)).recordDetect(isA(DetectRequest.class),eq("en"));
    }

    @Test
    public void should_return_language() {
        renter = new RenterBuilder(renterRepository).WithAppSecret(UUID.randomUUID().toString()).Build();
        ResponseEntity<AccessTokenResponse> accessTokenResponse = generateAccessToken();

        when(msTranslateProvider.detect(isA(String.class))).thenReturn("en");
        DetectRequest detectRequest = new DetectRequest();
        detectRequest.setContent("hello");
        detectRequest.setAccessToken(accessTokenResponse.getBody().getAccessToken());

        ResponseEntity<DetectResponse> response = sendDetectLanguageRequest(detectRequest);

        Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
        Assert.assertEquals("en", response.getBody().getLanguage());
        Assert.assertEquals(HttpStatus.OK.value(), response.getBody().getCode());
    }

    @Test
    public void should_return_forbidden_when_access_token_invalid() {
        when(msTranslateProvider.detect(isA(String.class))).thenReturn("en");
        DetectRequest detectRequest = new DetectRequest();
        detectRequest.setContent("hello");
        detectRequest.setAccessToken("invalidAccessToken");

        ResponseEntity<DetectResponse> response = sendDetectLanguageRequest(detectRequest);

        Assert.assertEquals(HttpStatus.FORBIDDEN, response.getStatusCode());
        Assert.assertEquals(HttpStatus.FORBIDDEN.value(), response.getBody().getCode());
    }

    @Test
    public void should_bad_request_when_content_can_not_be_detected() {
        DetectRequest detectRequest = new DetectRequest();
        detectRequest.setContent("");

        ResponseEntity<DetectResponse> response = sendDetectLanguageRequest(detectRequest);

        Assert.assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
        Assert.assertEquals(HttpStatus.BAD_REQUEST.value(), response.getBody().getCode());
    }

    private ResponseEntity sendDetectLanguageRequest(DetectRequest request) {

        return this.testRestTemplate.postForEntity("/api/translates/detect", request, DetectResponse.class);
    }

    private ResponseEntity<AccessTokenResponse> sendGenerateAccessTokenRequest(AccessTokenGenerateRequest request) {
        return this.testRestTemplate.postForEntity("/api/oauth/generate", request, AccessTokenResponse.class);
    }

    private ResponseEntity<AccessTokenResponse> generateAccessToken() {
        return sendGenerateAccessTokenRequest(new AccessTokenGenerateRequest(renter.getAppSecret(), "Secret"));
    }
}
